#include <stdio.h>

#include "wbio.h"

//#define DEBUG
//#define _FPGA_
#define TIMER0  0

#define printf	sysprintf

//#define DMAC_SCATTER_GETTER
//#define _USE_DAT3_DETECT_
#define USE_ECC4

//-- function return value
#define	   Successful  0
#define	   Fail        1

#ifdef ECOS
#define sysGetTicks(TIMER0)  cyg_current_time()
//#define printf	diag_printf
#endif

// extern global variables
extern UINT32 _fmi_uFMIReferenceClock;
extern UINT32 _fmi_uFirst_L2P;
extern BOOL volatile _fmi_bIsSDDataReady;
extern BOOL volatile _fmi_bIsMSDataReady, _fmi_bIsMSTimeOut;

#define STOR_STRING_LEN	32

/* we allocate one of these for every device that we remember */
typedef struct disk_data_t
{
    struct disk_data_t  *next;           /* next device */

    /* information about the device -- always good */
	unsigned int  totalSectorN;
	unsigned int  diskSize;			/* disk size in Kbytes */
	int           sectorSize;
    char          vendor[STOR_STRING_LEN];
    char          product[STOR_STRING_LEN];
    char          serial[STOR_STRING_LEN];
} DISK_DATA_T;


typedef struct dmac_desc_t {
	UINT32 uPhyAddress;
	UINT32 uSectorCount;
} DMAC_DESC_T;
extern DMAC_DESC_T DMAC_DESC[32];


typedef struct fmi_sd_info_t
{
	UINT32	uCardType;		// sd2.0, sd1.1, or mmc
	UINT32	uRCA;			// relative card address
	BOOL	bIsCardInsert;
} FMI_SD_INFO_T;

extern FMI_SD_INFO_T *pSD0, *pSD1;

typedef struct fmi_ms_info_t
{
	UINT32	uCardType;
	UINT32	uSectorPerFlash;
	UINT32	uBlockPerFlash;
	UINT32	uSectorPerBlock;
	UINT32	uBlockSize;
	BOOL	bIsMSProParallel;
	BOOL	bIsCardInsert;
} FMI_MS_INFO_T;

extern FMI_MS_INFO_T *pMS0, *pMS1;

/* TPC command set */
#define MS_READ_LONG_DATA	0x02	/* same as READ_PAGE_DATA */
#define MS_READ_PAGE_DATA	0x02
#define MS_READ_SHORT_DATA	0x03
#define MS_READ_REG			0x04
#define MS_GET_INT			0x07
#define MS_WRITE_LONG_DATA	0x0D	/* same as WRITE_PAGE_DATA */
#define MS_WRITE_PAGE_DATA	0x0D
#define MS_WRITE_SHORT_DATA	0x0C
#define MS_WRITE_REG		0x0B
#define MS_SET_RW_REG_ADRS	0x08
#define MS_SET_CMD			0x0E
#define MS_EX_SET_CMD		0x09

/* Memory access command (send with SET_CMD TPC and EX_SET_CMD TPC) */
/* Memory Stick */
#define MS_BLOCK_READ	0xAA  /* read data from the specified block */
#define MS_BLOCK_WRITE	0x55  /* write data to the specified block */
#define MS_BLOCK_END	0x33  /* stop BLOCK_READ/BLOCK_WRITE */
#define MS_BLOCK_ERASE	0x99  /* erase all data in specified block */
#define MS_FLASH_STOP	0xCC  /* force all flash memory operation to stop */
#define MS_SLEEP		0x5A  /* stop the clock generation inside the MS */
#define MS_CLEAR_BUF	0xC3  /* clear a page buffer */
#define MS_RESET		0x3C  /* reset the controller, init register and clear page buffer */

/* Memory Stick PRO */
#define MS_READ_DATA	0x20  /* read data consecutively from the assigned address in user area */
#define MS_WRITE_DATA	0x21  /* write data consecutively to the assigned address in user area */
#define MS_READ_ATRB	0x24  /* read data consecutively from the assigned address in attribute information area */
#define MS_STOP			0x25  /* stop the READ_DATA, WRITE_DATA, READ_ATRB, ERASE, and FORMAT */
#define MS_ERASE		0x26  /* erase data from the assigned address in user area */
#define MS_SET_IBD		0x46  /* write Information Block Data */
#define MS_GET_IBD		0x47  /* read Information Block Data */
#define MS_FORMAT		0x10  /* self-format with unique value */
#define MS_PRO_SLEEP	0x11  /* shift to low power consumption mode */

/* Memory Stick */
struct msSegment
{
	short msStartLogicalBlock;
	short msEndLogicalBlock;
};

/* MSPRO Device Information Entry */
typedef struct
{
	UINT32	msAddr;
	UINT32	msSize;
	UINT8	msDeviceID;
	UINT8	msReserved[3];

} FMI_MSPRO_DEVICE_INFO_ENTRY;

/* MSPRO System Information Structure */
typedef struct
{
	INT8	msClass;
	INT8	msTemp1;
	INT16	msBlockSize;
	INT16	msTotalBlock;
	INT16	msUserAreaBlock;
	INT16	msPageSize;
	INT16	msTemp2;
	INT8	msAsmDate[8];
	INT8	msSerialNo[4];
	INT8	msTemp3;
	INT8	msTemp4[3];
	INT8	msTemp5[2];
	INT8	msMemModel[2];
	INT8	msTemp6[4];
	INT8	msVcc;
	INT8	msVpp;
	INT8	msTemp7[2];
	INT8	msTemp8[2];
	INT16	msStartSec;
	INT16	msUnitSize;
	INT8	msSubClass;
	INT8	msTemp9[4];
	INT8	msInterfaceType;
	INT8	msTemp10[2];
	INT8	msFormatType;
	INT8	msTemp11;
	INT8	msDeviceType;
	INT8	msTemp12[7];
	INT8	msPROID[16];
	INT8	msTemp13[16];

} FMI_MSPRO_SYS_INFO;


// function declaration
#ifdef DMAC_SCATTER_GETTER
INT  dmacSetDescriptor(UINT32 uaddr, UINT32 ucount);
#endif

// SD functions
INT  fmiSDCommand(FMI_SD_INFO_T *pSD, UINT8 ucCmd, UINT32 uArg);
INT  fmiSDCmdAndRsp(FMI_SD_INFO_T *pSD, UINT8 ucCmd, UINT32 uArg, INT nCount);
INT  fmiSDCmdAndRsp2(FMI_SD_INFO_T *pSD, UINT8 ucCmd, UINT32 uArg, UINT32 *puR2ptr);
INT  fmiSDCmdAndRspDataIn(FMI_SD_INFO_T *pSD, UINT8 ucCmd, UINT32 uArg);
INT  fmiSD_Init(FMI_SD_INFO_T *pSD);
INT  fmiSelectCard(FMI_SD_INFO_T *pSD);
VOID fmiGet_SD_info(FMI_SD_INFO_T *pSD, DISK_DATA_T *_info);
INT  fmiSD_Read_in(FMI_SD_INFO_T *pSD, UINT32 uSector, UINT32 uBufcnt, UINT32 uDAddr);
INT  fmiSD_Write_in(FMI_SD_INFO_T *pSD, UINT32 uSector, UINT32 uBufcnt, UINT32 uSAddr);

// MS functions
int  fmiMS_Initial(FMI_MS_INFO_T *pMS);
VOID fmiGet_MS_info(FMI_MS_INFO_T *pMS, DISK_DATA_T *_info);
INT  fmiMS_Read_in(FMI_MS_INFO_T *pMS, UINT32 SectorNo, UINT32 SectorCount, char *pUploadBuf);
INT  fmiMS_Write_in(FMI_MS_INFO_T *pMS, UINT32 SectorNo, UINT32 SectorCount, char *pLoadBuf);
